Developing Machines For Buzz

To create machines, you need MS Visual C++ 5.0 with the latest service pack installed. Try building one of the example machines found in the Buzz\Dev folder first to make sure it works.

Before you start to make anything yourself, study the sourcecode for the other machines and make try to understand it. It's currently the only way to learn to code these machines, because I'm too lazy to write cool tutorials.

Here are the steps needed to create a machine:

Create the VC project:

  1. Create new Win32 Dynamic-Link library project
  2. Set code generation settings to:
    • Processor: Pentium
    • Use Run-Time Library: Debug Multithreaded DLL (debug) and Multitheaded DLL (release)
    • Calling convention: __fastcall
    • Struct member alignment: 4 bytes
  3. Add a new C++ source file to the project and put #include "MachineInterface.h" on the top

Create instances of CMachineParameter:

CMachineParameter const paraCutoff = 
{
	pt_byte,                    // type
	"Cutoff",                   // short (one or two words) name 
	"Cutoff frequency (0-7F)",  // longer description 
	0,                          // minumum value
	127,                        // maximum value
	255,                        // some value outside [min..max] range 
	MPF_STATE                   // flags
};

CMachineParameter const paraNote = 
{
	pt_note,                    // type
	"Note",                     // short (one or two words) name 
	"Note",                     // longer description 
	NOTE_MIN,                   // always same for notes
	NOTE_MAX,                   // "
	NOTE_NO,                    // "
	0                           // flags
};

Create array of pointers to the parameter descriptors:

CMachineParameter const *pParameters[] = 
{
	// global parameters first
	¶Cutoff,
	¶Resonance,

	// followed by track parameters 
	¶Note
};

Create a classes that you use to access the values (not required, but makes it a lot easier):

#pragma pack(1)			// <- don't forget that

class gvals
{
public:
	byte cutoff;		// in the same order as in pParameters
	byte resonance;
};

class tvals
{
public:
	byte note;
};

#pragma pack()

Create an instance of CMachineInfo:

#define MAX_TRACKS	16

CMachineInfo const MacInfo = 
{
	MT_GENERATOR,                    // type, MT_GENERATOR or MT_EFFECT
	MI_VERSION,                      // version, always set this to MI_VERSION
	1,                               // minimum number of tracks
	MAX_TRACKS,                      // maximum number of tracks
	2,                               // number of global parameters
	1,                               // number of track parameters
	pParameters,                     // pointer to list of parameters
	0,                               // number of attributes
	NULL,                            // pointer to list of attributes
#ifdef _DEBUG
	"Hoax Generator (debug build)",  // name for debug build
#else
	"Hoax Generator",                // name for release build
#endif
	"Hoax",                          // short name
	"Hoax Man",                      // your name
	NULL                             // list of commands 
};

Derive new class from CMachineInterface:

class mi : public CMachineInterface
{
public:	
	mi();
	virtual ~mi();		// must be virtual 

	virtual void Init(CMachineDataInput * const pi);
	virtual void Tick();
	virtual bool Work(float *psamples, int numsamples, int const mode);
	virtual void SetNumTracks(int const n);
	

private:	
	int numTracks;
	gvals gval;
	tvals tval[MAX_TRACKS];

};

Use DLL_EXPORTS macro to create the necessary export functions:

DLL_EXPORTS

Implement your mi methods:

// intialize pointers to your values in the constuctor
mi::mi()	
{
	GlobalVals = &gval;
	TrackVals = tval;
	AttrVals = NULL;
}

mi::~mi()
{
	// free any memory you allocated here
}

void mi::Init(CMachineDataInput * const pi)
{
	// initialize the machine
	// you can ignore pi if you haven't implemented the 'Save' method
}

// this is called by buzz after Init and every time the user adds/deletes a track
void mi::SetNumTracks(int const n)
{
	numTracks = n;
}

void mi::Tick()
{
	if (gval.cutoff != paraCutoff.NoValue)
	{
		// gval.cutoff contains new cutoff value
	}

	if (gval.resonance != paraResonance.NoValue)
	{
	}

	for (int c = 0; c < numTracks; c++)
	{
		if (tval[c].note == NOTE_OFF)
		{
			// note off on track c 
		}
		else if (tval[c].note != NOTE_NO)
		{
			// note on track c
		}
	}

}

bool mi::Work(float *psamples, int numsamples, int const mode)
{
	// generators can ignore the 'mode' argument
	
	// generate 'numsamples' samples to 'psamples' here
	
	// return true if you generated something, false if not
}

BM* Format

This text file explains the inner workings of the BMW and BMX formats.



Midi Recording

This text file explains the inner workings of the MIDI Recording.



Machine Skins

This text file explains the inner workings of the skins.